﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;
using EditAnyString.Models;

namespace EditAnyString.MVC
{
	public abstract class EASWebViewForm<TModel> : WebViewPage<TModel>
	{
		private const string REQUEST_STRINGS_KEY = "EAS.REQUEST_STRINGS";

		private EASHandler _eas;
		private EASRawHandler _rawEAS;

		private Providers.IEASStorageProvider _storageProvider;
		private Providers.IEASEditAuthorizationProvider _authProvider;

		private void ensureProviders()
		{
			if( _storageProvider == null )
				// get storage provider
				_storageProvider = DependencyResolver.Current.GetService<Providers.IEASStorageProvider>();
			if( _authProvider == null )
				_authProvider = DependencyResolver.Current.GetService<Providers.IEASEditAuthorizationProvider>();
		}

		public bool CanEditEAS
		{
			get
			{
				ensureProviders();
				return _authProvider.CanEdit;
			}
		}

		public EASHandler S
		{
			get
			{
				if( _eas == null )
				{
					ensureProviders();
					string vp = VirtualPath;
					_eas = ( t, idx, args ) => getHtmlString( vp, t, idx, args );
				}
				return _eas;
			}
		}

		public EASRawHandler R
		{
			get
			{
				if( _rawEAS == null )
				{
					ensureProviders();
					string vp = VirtualPath;
					_rawEAS = ( t, idx, args ) => getRawString( vp, t, idx, args );
				}
				return _rawEAS;
			}
		}

		public IEnumerable<EditableString> RequestEditableStrings
		{
			get
			{
				var strings = HttpContext.Current.Items[ REQUEST_STRINGS_KEY ] as HashSet<EditableString>;
				if( strings == null )
					return new List<EditableString>();
				return strings;
			}
		}

		private void addRequestString( EditableString str )
		{
			var strings = HttpContext.Current.Items[ REQUEST_STRINGS_KEY ] as HashSet<EditableString>;
			if( strings == null )
			{
				// create and add to context
				strings = new HashSet<EditableString>();
				HttpContext.Current.Items[ REQUEST_STRINGS_KEY ] = strings;
			}
			strings.Add( str );
		}

		private IHtmlString getHtmlString( string context, string t, int? idx, params object[] args )
		{
			var found = _storageProvider.GetString( context, t, idx );
			string v = t;
			if( found != null ) // if we have some data, then this means that we can try to edit it
			{
				if( _authProvider.CanInlineEdit )
				{
					v = "<span class='easEdit' key='" + found.Key + "'>" + found.Value + "</span>";
					// add also entry to our list of all strings
					addRequestString( found );
				}
				else
					v = found.Value;
			}
			return MvcHtmlString.Create( string.Format( v, args ) );
		}

		private string getRawString( string context, string t, int? idx, params object[] args )
		{
			var found = _storageProvider.GetString( context, t, idx );
			if( found != null )
			{
				if( _authProvider.CanInlineEdit )
					addRequestString( found );
				return string.Format( found.Value, args );
			}
			return string.Format( t, args );
		}
	}
}
